﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace nblTool.utils
{
    internal class ByteUtils
    {
        public static byte[] ListToBytes(List<byte[]> values)
        {
            int lengthByte = 0;
            values.ForEach(v => { lengthByte += v.Length; });
            /*for (byte[] value : values)
            {
                lengthByte += value.length;
            }*/
            byte[] allBytes = new byte[lengthByte];
            int countLength = 0;
            /*for (byte[] b : values)
            {
                Array.Copy(b, 0, allBytes, countLength, b.Length);
                countLength += b.Length;
            }*/
            values.ForEach(v => { Array.Copy(v, 0, allBytes, countLength, v.Length);
                countLength += v.Length;
            });
            return allBytes;
        }

        public static byte[] addBytes(byte[] data1, byte[] data2)
        {
            int L1 = 0;
            int L2 = 0;
            if (data1!=null)
            {
                L1 = data1.Length;
            }
            if (data2!=null)
            {
                L2 = data2.Length;
            }
            byte[] data3 = new byte[L1 + L2];
            if (data1 != null)
            {
                Array.Copy(data1, 0, data3, 0, L1);
            }
            //Array.Copy(data1, 0, data3, 0, L1);
            if(data2 != null)
            {
                Array.Copy(data2, 0, data3, L1, L2);
            }
           
            
            return data3;

        }

        public static byte[] delectHeadBytes(byte[] data, int startLen)
        {
            int length = data.Length;
            byte[] valueDlms = new byte[length - startLen];
            Array.Copy(data, startLen, valueDlms, 0, length - startLen);
            return valueDlms;
        }

        public static byte[] delectAfterBytes(byte[] data, int endLen)
        {
            int length = data.Length;
            byte[] valueDlms = new byte[length - endLen];
            Array.Copy(data, 0, valueDlms, 0, length - endLen);
            return valueDlms;
        }

        public static byte[] byteTrimEnd(byte[] data)
        {
            List<byte> list = data.ToList();
            for (int i = data.Length-1; i >= 0; i--)
            {
                if (data[i]==0x00)
                {
                    list.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }
            return list.ToArray();
        }
        public static byte[] getHeadBytes(byte[] data, int startLen)
        {
            if (startLen > data.Length)
            {
                return data;
            }
            byte[] valueDlms = new byte[startLen];
            Array.Copy(data, 0, valueDlms, 0, startLen);
            return valueDlms;
        }

        public static String bytesToHexString(byte[] bArray)
        {
            StringBuilder sb = new StringBuilder(bArray.Length);
            String sTemp;
            for (int i = 0; i < bArray.Length; i++)
            {
                
                //sTemp = Integer.toHexString(0xFF & bArray[i]);
                sTemp = String.Format("{0:X}", 0xFF & bArray[i]);
                if (sTemp.Length < 2)
                    sb.Append(0);
                sb.Append(sTemp.ToUpper());
                //sb.append(" ");
            }
            return sb.ToString();
        }

        public static String bytesToHexString(List<byte> bArray)
        {
            StringBuilder sb = new StringBuilder(bArray.Count);
            String sTemp;
            for (int i = 0; i < bArray.Count; i++)
            {

                //sTemp = Integer.toHexString(0xFF & bArray[i]);
                sTemp = String.Format("{0:X}", 0xFF & bArray[i]);
                if (sTemp.Length < 2)
                    sb.Append(0);
                sb.Append(sTemp.ToUpper());
                //sb.append(" ");
            }
            return sb.ToString();
        }

        /**
         * 将低字节数组转换为int
         * @param b byte[]
         * @return int
         */
        public static int lBytesToInt(byte[] b)
        {
            int s = 0;
            for (int i = 0; i < 3; i++)
            {
                if (b[3 - i] >= 0)
                {
                    s = s + b[3 - i];
                }
                else
                {
                    s = s + 256 + b[3 - i];
                }
                s = s * 256;
            }
            if (b[0] >= 0)
            {
                s = s + b[0];
            }
            else
            {
                s = s + 256 + b[0];
            }
            return s;
        }

        /**
         * 将高字节数组转换为int
         * @param b byte[]
         * @return int
         */
        public static int hBytesToInt(byte[] b)
        {
            int s = 0;
            for (int i = 0; i < 3; i++)
            {
                if (b[i] >= 0)
                {
                    s = s + b[i];
                }
                else
                {
                    s = s + 256 + b[i];
                }
                s = s * 256;
            }
            if (b[3] >= 0)
            {
                s = s + b[3];
            }
            else
            {
                s = s + 256 + b[3];
            }
            return s;
        }

        /**
         * 高字节数组到short的转换
         * @param b byte[]
         * @return short
         */
        public static short hBytesToShort(byte[] b)
        {
            int s = 0;
            if (b[0] >= 0)
            {
                s = s + b[0];
            }
            else
            {
                s = s + 256 + b[0];
            }
            s = s * 256;
            if (b[1] >= 0)
            {
                s = s + b[1];
            }
            else
            {
                s = s + 256 + b[1];
            }
            short result = (short)s;
            return result;
        }

        /**
         * 将int转为低字节在前，高字节在后的byte数组
         * @param n int
         * @return byte[]
         */
        public static byte[] toLH(int n)
        {
            byte[] b = new byte[4];
            b[0] = (byte)(n & 0xff);
            b[1] = (byte)(n >> 8 & 0xff);
            b[2] = (byte)(n >> 16 & 0xff);
            b[3] = (byte)(n >> 24 & 0xff);
            return b;
        }

        /**
         * 将int转为高字节在前，低字节在后的byte数组
         * @param n int
         * @return byte[]
         */
        public static byte[] toHH(int n)
        {
            byte[] b = new byte[4];
            b[3] = (byte)(n & 0xff);
            b[2] = (byte)(n >> 8 & 0xff);
            b[1] = (byte)(n >> 16 & 0xff);
            b[0] = (byte)(n >> 24 & 0xff);
            return b;
        }

        /// <summary>
        /// 生成字节
        /// </summary>
        /// <param name="data">位数据</param>
        /// <returns></returns>
        public static byte GetBitArray(IEnumerable<bool> data)
        {
            //把位数据集合反转
            //data=data.Reverse();

            //定义初始字节，值为0000 0000
            byte temp = 0x00;

            //循环计数
            int index = 0;

            //循环位集合
            foreach (bool item in data)
            {
                //判断每一位的数据，为true则左移一个1到对应的位置
                if (item) temp = (byte)(temp | (0x01 << index));

                //计数+1
                index++;
            }

            //返回最后使用位数据集合生成的二进制字节
            return temp;
        }
        /// <summary>
        /// 获取1个字节的8位二进制
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static List<bool> GetBitBool(byte data)
        {
            List<bool> bools = new List<bool>();

            for (int i = 0; i < 8; i++)
            {
                var bit = (data >> i) & 0x01;
                bools.Add(bit == 1 ? true : false);

            }
            return bools;
        }

        /// <summary>
        /// 根据bit位获取字节数
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] GetByteArrary(List<bool> value)
        {

            List<byte> valueTemp = new List<byte>();
            //由于一个字节只有八个位，所以如果需要写入的值超过了八个，
            //则需要生成一个新的字节用以存储，
            //所以循环截取输入的值，然后生成对应的写入值字节
            for (int i = 0; i < value.Count(); i += 8)
            {
                //写入值字节临时字节集合
                List<bool> temp = value.Skip(i).Take(8).ToList();

                //剩余位不足八个，则把剩下的所有位都放到同一个字节里
                if (temp.Count != 8)
                {
                    //取余获取剩余的位的数量
                    int m = value.Count() % 8;
                    //截取位放入临时字节集合中
                    temp = value.Skip(i).Take(m).ToList();
                }

                //获取位生成的写入值字节
                byte tempByte = GetBitArray(temp);

                //将生成的写入值字节拼接到写入值字节集合中
                valueTemp.Add(tempByte);
            }
            byte[] bytes = valueTemp.ToArray();
            Array.Reverse(bytes);
            return bytes;
        }
    }
}
